//
//  ImportFilesManager.swift
//  TimMusic
//
//  Created by nkl on 2024/10/14.
//

import Foundation
import TSVideoKit
import TZImagePickerController

class ImportFilesManager: NSObject, TZImagePickerControllerDelegate, UIDocumentPickerDelegate {
    static let shared = ImportFilesManager()

    func openPhotoLibrary(parent: UIViewController) {
        guard let vc = TZImagePickerController(maxImagesCount: 9, delegate: self) else { return }
        vc.allowPickingImage = false
        vc.allowPreview = false
        vc.allowTakeVideo = false
        vc.allowTakePicture = false
        vc.allowCameraLocation = false
        vc.allowPickingMultipleVideo = true
        vc.allowPickingOriginalPhoto = false
        vc.naviBgColor = UIColor.white
        vc.naviTitleColor = UIColor.black
        vc.pickerDelegate = self
        parent.present(vc, animated: true)
    }

    func imagePickerController(_ picker: TZImagePickerController!, didFinishPickingPhotos photos: [UIImage]!, sourceAssets assets: [Any]!, isSelectOriginalPhoto: Bool) {
        DispatchQueue.global().async {
            for asset in assets {
                if let mAsset = asset as? PHAsset {
                    TZImageManager.default().requestVideoURL(with: mAsset) { videoUrl in
                        if let url = videoUrl {
                            self.copyFileToUrl(url: url)
                        }
                    } failure: { _ in
                    }
                }
            }
        }
    }

    func copyFileToUrl(url: URL) {
        let fileId = UUID().uuidString
        let path = TSVideoOperator.shared.configuration.fileDir.appendingPathComponent(fileId)
        let destinationURL = uniqueFileURL(at: path, originalURL: url)
        do {
            try FileManager.default.copyItem(at: url, to: destinationURL)
            Task {
                await self.importVideo(videoId: fileId, from: destinationURL)
            }

        } catch {
            print(error.localizedDescription)
        }
    }

    private func importVideo(videoId: String, from url: URL) async {
        let asset = AVAsset(url: url)
        let imageData : AudioMetadata
        if asset.isAudio {
            imageData = await asset.extractMetadata()
        }else{
            let image = await asset.generateThumbnail()
            imageData = AudioMetadata(artwork: image, artist: "Unknown")
        }
       

        await MainActor.run {
            let title = url.lastPathComponent
            let pathExt = url.pathExtension.lowercased()
            let vPath = videoId + "/" + title

            let audios = ["mp3", "wav", "m4a"]
            var isRing: Bool = false
            if audios.contains(pathExt) {
                isRing = true
            }
            let mData =  imageData.artwork?.jpegData(compressionQuality: 0.8)
            let defaultData = UIImage(named: "ic_placeholder")?.jpegData(compressionQuality: 0.8)
            let finalData = mData ?? defaultData
            TSVideoOperator.shared.dataManager.createVideo(videoId: videoId, videoUrl: nil, audioStream: nil, videoStream: nil, videoTitle: title, artist: imageData.artist, artwork: finalData, online: false, customTag: isRing, status: .cached, vPath: vPath) { _ in
                NotificationCenter.default.post(name: .K_ImportSuccessNotifaction, object: nil)
            }
        }
    }

    func uniqueFileURL(at directory: URL, originalURL: URL) -> URL {
        let fileManager = FileManager.default

        // 检查目录是否存在，如果不存在则创建目录
        if !fileManager.fileExists(atPath: directory.path) {
            do {
                try fileManager.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
            } catch {
                // 这里可以选择抛出错误或处理错误
            }
        }

        let originalFilename = originalURL.deletingPathExtension().lastPathComponent
        let fileExtension = originalURL.pathExtension
        var uniqueURL = directory.appendingPathComponent(originalFilename).appendingPathExtension(fileExtension)

        var counter = 1
        while fileManager.fileExists(atPath: uniqueURL.path) {
            uniqueURL = directory.appendingPathComponent("\(originalFilename)-\(counter)").appendingPathExtension(fileExtension)
            counter += 1
        }

        return uniqueURL
    }

    func openFileDocument(parent: UIViewController, completion: ((Bool, String?, URL?) -> Void)?) {
        let documentTypes = ["public.mp3", "public.movie"]
        // 音频 mp3，wav，m4a
        // .MP3; .AAC; .WAV; .WMA; .CDA; .FLAC; .M4A; .MID; .MKA; .MP2; .MPA; .MPC; .APE; .OFR; .OGG; .RA; .WV; .TTA; .AC3; .DTS
        // 视频 mp4，avi, wmv，mov，mpg(mpeg)
        let documentVC = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import)
        //        Appropriate
        //        let documentVC = UIDocumentPickerViewController(forOpeningContentTypes: [.aiff, .audio, .avi, .wav, .mp3, .movie])
        documentVC.delegate = self
        documentVC.modalPresentationStyle = .fullScreen
        parent.present(documentVC, animated: true)
    }

    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        if let first = urls.first {
            copyFileToUrl(url: first)
        }
    }
}

extension AVAsset {
    var isVideo: Bool {
        return tracks(withMediaType: .video).count > 0
    }

    var isAudio: Bool {
        return tracks(withMediaType: .audio).count > 0 && !isVideo
    }

    func generateThumbnail() async -> UIImage? {
        await withCheckedContinuation { continuation in
            generateThumbnail { image in
                continuation.resume(returning: image)
            }
        }
    }

    private func generateThumbnail(completion: @escaping (UIImage?) -> Void) {
        DispatchQueue.global().async {
            let imageGenerator = AVAssetImageGenerator(asset: self)
            imageGenerator.appliesPreferredTrackTransform = true
            let time = CMTime(seconds: 0.0, preferredTimescale: 600)
            let times = [NSValue(time: time)]
            imageGenerator.generateCGImagesAsynchronously(forTimes: times, completionHandler: { _, image, _, _, _ in
                if let image = image {
                    completion(UIImage(cgImage: image))
                } else {
                    completion(nil)
                }
            })
        }
    }

    private func extractArtwork() -> UIImage? {
         let metadata = self.metadata
         for item in metadata {
             if let key = item.commonKey?.rawValue, key == "artwork" {
                 if let data = item.dataValue, let image = UIImage(data: data) {
                     return image
                 }
             }
         }
         return UIImage(named: "ic_placeholder")
     }
    
    private func extractArtistInfo() -> String {
        let metadata = self.metadata
        for item in metadata {
            if let key = item.commonKey?.rawValue, key == "artist" {
                return item.value as? String ?? "Unknown"
            }
        }
        return "Unknown"
    }
    
    func extractMetadata() async -> AudioMetadata {
        await withCheckedContinuation { continuation in
            let artwork = self.extractArtwork()
            let artist = self.extractArtistInfo()
            let metadata = AudioMetadata(artwork: artwork, artist: artist)
            continuation.resume(returning: metadata)
        }
    }
}


struct AudioMetadata {
    let artwork: UIImage?
    let artist: String
}
